#include<iostream>
using namespace std;

#include<unistd.h>
#include<signal.h>

#include<vector>

#define CHILD_NUM 10

void handler(int signal)
{
    cout << "father get a signal ::" << signal << endl;
}

int main()
{
    signal(SIGCHLD, handler);
    
    if(fork() == 0)
    {
        cout << "child [" << getpid() << "] is created" << endl;
        sleep(100);
        exit(0); 
    }

    while(1)
    {
        cout << "father[" << getpid() << "] do own things" << endl;
        sleep(1);
    }

    return 0;
}

// void handler(int signal)
// {
//     cout << endl;
//     cout << endl;
//     cout << "========================================" << endl;
//     cout << "father get a signal ::" << signal << endl;

//     cout << "start to wait childs" << endl;

//     pid_t id = 0;
//     while((id = waitpid(-1, nullptr, WNOHANG)) > 0)
//     {
//         cout << "wait [" << id << "] success" << endl;
//     }

//     cout << "========================================" << endl;
//     cout << endl;
//     cout << endl;
// }

// int main()
// {
//     // 捕捉SIGCHLD信号
//     signal(SIGCHLD, handler);

//     for(int i = 0; i < CHILD_NUM; ++i)
//     {
//         // 创建CHILD_NUM个子进程
//         pid_t id = fork();
//         if(id == 0)
//         {// 子进程
//             // 睡1s直接退出
//             sleep(1);
//             exit(0);
//         }

//         // 父进程记录下每个子进程的pid
//         cout << "child[" << id << "] is created" << endl;
//     }

//     while(1)
//     {
//         // 这里代表父进程做自己的事情
//         cout << "father[" << getpid() << "] do own things" << endl;
//         sleep(1);
//     }


//     return 0;
// }



// vector<pid_t> pids;

// void handler(int signal)
// {
//     cout << endl;
//     cout << endl;
//     cout << "========================================" << endl;
//     cout << "father get a signal ::" << signal << endl;

//     cout << "start to wait childs" << endl;

//     for(int i = 0; i < CHILD_NUM; ++i)
//     {
//         pid_t ret;
//         if(pids[i] != 0) // pid不为0才等待
//         {
//             cout << "wait[" << pids[i] << "]";
//             ret = waitpid(pids[i], nullptr, WNOHANG);
//             assert(ret != -1);
//             if(ret > 0)
//             {
//                 // 等待成功后就直接将该位置的pid改为0
//                 cout << "success" << endl;
//                 pids[i] = 0;
//             }
//             else if(ret == 0)
//             { // 等于0说明子进程还在跑
//                 cout << "fail, it's still running" << endl;
//             }
//         }
//     }

//     cout << "========================================" << endl;
//     cout << endl;
//     cout << endl;
// }

// int main()
// {
//     // 捕捉SIGCHLD信号
//     signal(SIGCHLD, handler);

//     for(int i = 0; i < CHILD_NUM; ++i)
//     {
//         // 创建CHILD_NUM个子进程
//         pid_t id = fork();
//         if(id == 0)
//         {// 子进程
//             // 睡1s直接退出
//             sleep(1);
//             exit(0);
//         }

//         // 父进程记录下每个子进程的pid
//         pids.push_back(id);
//         cout << "child[" << id << "] is created" << endl;
//     }

//     while(1)
//     {
//         // 这里代表父进程做自己的事情
//         cout << "father[" << getpid() << "] do own things" << endl;
//         sleep(1);
//     }


//     return 0;
// }



// int main()
// {
//     // 父进程对17号信号注册忽略动作
//     signal(SIGCHLD, SIG_IGN);

//     if(fork() == 0)
//     {
//         // 子进程睡一秒后直接退出
//         sleep(1);
//         cout << "child " << getpid() << "\tquit" << endl;
//         exit(0);
//     }

//     while(1)
//     {
//         cout << getpid() << "  parent running" << endl;
//         sleep(1);
//     }

//     return 0;
// }


// void handler(int signal)
// {
//     cout << "get a signal ::" << signal << endl;
// }

// int main()
// {
//     // 父进程捕捉17号信号
//     signal(SIGCHLD, SIG_IGN);

//     if(fork() == 0)
//     {
//         // 子进程睡一秒后直接退出
//         sleep(1);
//         cout << "child " << getpid() << "\tquit" << endl;
//         exit(0);
//     }

//     while(1)
//     {
//         sleep(1);
//     }
    

//     return 0;
// }



// int flag = 0;

// void changeFlag(int signum)
// {
//     (void)signum;
//     cout <<"change flag: "<< flag;
//     flag = 1;
//     cout << "->" << flag << endl;
// }

// int main()
// {
//     signal(2, changeFlag);
//     while(!flag);
//     cout << "进程正常退出后：" << flag << endl;
// }




// volatile int flag = 0;

// void handler(int signal)
// {
//     cout << endl;
//     cout << "=================" << endl;
//     cout << "catch signal ::" << signal << endl;
//     // 自定义方法中修改flag
//     flag = 1;
//     cout << "\t修改flag ->" << flag << endl;
//     cout << "=================" << endl;
// }

// int main()
// {
//     // 捕捉2号信号
//     signal(SIGINT, handler);

//     cout << getpid() << "running" << endl;
//     // flag为0时就一直循环，当发送2号信号后，flag就会变为1，此时就会退出
//     while(!flag);

//     cout << "flag changed\t" << getpid() << " exit" << endl;

//     return 0;
// }




// // 打印获得到的位图
// void printPending(sigset_t& pending)
// {
//     for(int i = 1; i <= 31; ++i)
//     {
//         if(sigismember(&pending, i)) cout << "1";
//         else cout << "0";
//     }
//     cout << endl;
// }


// // 自定义方法
// void catchSignal(int signal)
// {
//     cout << "catch a signal ::" << signal  << endl;
//     sigset_t pending;

//     int count = 0;
//     while(1)
//     {
//         sigpending(&pending);
//         printPending(pending);
//         sleep(1);
//         ++count;
//         if(count == 20)
//         {
//             cout << "\tover" << endl;
//             break;
//         }
//     }
// }

// int main()
// {
//     // 设定2号信号处理动作为忽略
//     sigset(2, SIG_IGN);

//     cout << "process ::" << getpid() << "  runnig" << endl;

//     struct sigaction act, oact;
//     act.sa_flags = 0;
//     sigemptyset(&act.sa_mask);
//     act.sa_handler = catchSignal;

//     sigaddset(&act.sa_mask, 3);
//     sigaddset(&act.sa_mask, 4);
//     sigaddset(&act.sa_mask, 5);
//     sigaddset(&act.sa_mask, 6);
//     sigaddset(&act.sa_mask, 7);
//     sigaddset(&act.sa_mask, 8);

//     // 设置进当前调用进程的pcb中
//     sigaction(2, &act, nullptr);

//     while(1)
//     {
//         sleep(1);
//     };

//     return 0;
// }


// int main()
// {
//     // 接收一下2号信号
//     signal(2, catchSignal);

//     // 用户=================
//     // block屏蔽字
//     sigset_t bset;

//     // 初始化block屏蔽字
//     sigemptyset(&bset);

//     // 向bset中添加2号信号位
//     sigaddset(&bset, 2);// 这里的2可以换做SIGINT

//     // pending位图，不需要初始化，获取pending位图时会直接覆盖
//     sigset_t pending;

//     // 内核=================
//     // 将屏蔽字写入内核中
//     sigprocmask(SIG_BLOCK, &bset, nullptr);// 这里不需要获取前一次的block位图
    
//     int count = 0;
//     while(1)
//     {
//         ++count;
//         // 不断获取pending位图并打印
//         sigpending(&pending);
//         printPending(pending);
//         sleep(1);
//         if(count == 20) // 10秒后解除2号信号屏蔽
//         {
//             // 先除掉bset中的2号信号位
//             sigdelset(&bset, 2);
//             // 再写入内核中
//             sigprocmask(SIG_SETMASK, &bset, nullptr);
//             cout << "2号信号解除" << endl;
//         }
//     }

//     return 0;
// }


// 屏蔽所有信号
// // 用户=======================
// // pending位图
// sigset_t pending;


// // 初始化位图 pending 是否初始化是没有影响的，因为sigpending会将pending中的数据覆盖掉
// sigemptyset(&pending);

// // beset 表示当前block屏蔽字 obset表示前一次屏蔽字
// sigset_t bset;

// // block要初始化，因为要向其中添加信号位，都为零才能确定添加的是否正确
// sigemptyset(&bset);

// // 添加信号屏蔽字 将所有信号设置到bset中
// for(int i = 1; i <= 31; ++i)
// {
//     sigaddset(&bset, i);
// }

// // 内核=======================

// // 将block屏蔽字设置到内核中
// int n = sigprocmask(SIG_BLOCK, &bset, nullptr);
// assert(n == 0);
// (void)n;

// // 捕获所有普通信号
// for(int i = 1; i <= 31; ++i)
// {
//     signal(i, catchSignal);
// }

// while(1)
// {        
//     // 获取当前进程pending位图
//     sigpending(&pending);

//     // 打印pending位图
//     printPending(pending);
//     sleep(1);
// }